package reflect02;

import org.junit.Test;
import reflect01.Person;

import java.lang.reflect.Constructor;


/**
 * 反射(解剖出)构造方法
 * Class<T>:T代表字节码对象所表示的类
 * 基本的 Java 类型（boolean、byte、char、short、int、long、float 和 double）和关键字 void 也表示为 Class 对象。
 * 只需要将基本类型后面带上.class就表示Class的实例
 * Class类中成员方法:
 *   Constructor<T> getConstructor(Class<?>... parameterTypes)
 *           返回一个 Constructor 对象，它反映此 Class 对象所表示的类的指定公有(public)构造方法。
 *           <T>:表示当前字节码对象代表的类
 *
 *   Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
 *           获取类中声明的任意一个构造方法
 *
 *    T newInstance()
 *           只能利用该类的空参构造创建对象,不能利用有参构造创建对象
 *
 * Constructor类中的方法
 *   String getName()
 *           以字符串形式返回此构造方法的名称。
 *   T newInstance(Object... initargs)
 *           使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例，并用指定的初始化参数初始化该实例
 */
public class ReflectDemo01 {
   /* @Test
    public void testMethod01() throws Exception {
        // 1.获取字节码对象
        Class<Person> pCls = Person.class;
        // 2.获取构造方法
        Constructor<Person> cons = pCls.getConstructor();// y由于获取的是空参构造，所以不需要传递任何参数，因此Constructors方法也不需要传参数
        // 3.获取构造方法信息
        String name = cons.getName();
        System.out.println(name);

        // 4.利用构造方法创建对象
        Person person = cons.newInstance();// 利用空参构造创建对象
                                            // 类比 Person p = new Person();
        System.out.println(person);
    }

    @Test
    public void testMethod02() throws InstantiationException, IllegalAccessException {
        // 1.获取字节码对象
        Class<Person> pCls = Person.class;
        //2.直接利用Class类的newInstance()方法创建该类实例
        Person person = pCls.newInstance(); // 底层相当于 Person p = new Person();
        System.out.println(person);  // reflect01.Person@35851384
    }*/

   /* @Test
    public void testMethod03() throws Exception{
        // 1.获取字节码对象并获取有参构造
        Constructor<Person> cons = Person.class.getConstructor(String.class, int.class);
        // 获取指定参数为String,int类型的构造方法
        // 2.利用这个有参构造创建对象
        Person person = cons.newInstance("老王", 30);
        // 类比：Person p = new Person("老王",30);
        System.out.println(person); // Person{name='老王', age=30}
    }*/

    @Test
    public void testMethod04() throws Exception {
        // 1.获取字节码对象并获取有参构造
        Class<Person> pCls = Person.class;
        //2.获取构造方法
        //Constructor<Person> cons = pCls.getConstructor(String.class);
        Constructor<Person> cons = pCls.getDeclaredConstructor(String.class);

        //3.由于是将要利用私有构造方法创建对象,在类外无法调用私有构造方法,但是我们可以让java取消权限检查
        cons.setAccessible(true);

        //4.利用构造方法创建对象
        Person person = cons.newInstance("老李");
        System.out.println(person);
        // Person{name='老李', age=13}
    }
}
